#include <stdlib.h>
#include <string.h>

#include "seqlist.h"

int seqlist_init(seqlist_t **mylist, int size, int capacity)
{
	*mylist = malloc(sizeof(seqlist_t));
	if (NULL == *mylist)
		return -1;
	(*mylist)->arr = calloc(capacity, size);
	if (NULL == (*mylist)->arr) {
		free(*mylist);
		*mylist = NULL;
		return -1;
	}
	(*mylist)->nmemb = 0;
	(*mylist)->size = size;
	(*mylist)->capacity = capacity;

	return 0;
}

int seqlist_insert(seqlist_t *mylist, const void *data)
{
	if (seqlist_full(mylist))
		return -1;
	memmove((char *)mylist->arr + mylist->size, mylist->arr, \
			mylist->nmemb * mylist->size);
	memcpy(mylist->arr, data, mylist->size);
	mylist->nmemb++;

	return 0;
}

int seqlist_insert_tail(seqlist_t *mylist, const void *data)
{
	if (seqlist_full(mylist))	
		return -1;
	memcpy((char *)mylist->arr + mylist->nmemb * mylist->size, data, mylist->size);
	mylist->nmemb++;
	return 0;
}

int seqlist_empty(const seqlist_t *mylist)
{
	return mylist->nmemb == 0;
}

int seqlist_full(const seqlist_t *mylist)
{
	return mylist->nmemb == mylist->capacity;
}

void seqlist_traval(const seqlist_t *mylist, pri_t pri)
{
	int i;

	for (i = 0; i < mylist->nmemb; i++)
		pri((char *)mylist->arr + i * mylist->size);
}

void seqlist_destroy(seqlist_t **mylist)
{
	if (*mylist == NULL)
		return;

	free((*mylist)->arr);
	(*mylist)->arr = NULL;
	free(*mylist);
	*mylist = NULL;
}

static int __find(const seqlist_t *mylist, const void *key, cmp_t cmp)
{
	int i;

	for (i = 0; i < mylist->nmemb; i++) {
		if (0 == cmp((char *)mylist->arr + i * mylist->size, key))
			return i;
	}

	return -1;
}

int seqlist_delete(seqlist_t *mylist, const void *key, cmp_t cmp)
{
	int f;

	f = __find(mylist, key, cmp);
	if (-1 == f)
		return -1;
	memmove((char *)mylist->arr + f * mylist->size, \
			(char *)mylist->arr + (f + 1) * mylist->size, \
			(mylist->nmemb - (f + 1)) * mylist->size);
	// 多出来元素 最后一个位置
	memset((char *)mylist->arr + (mylist->nmemb - 1) * mylist->size, 0, mylist->size);
	mylist->nmemb--;

	return 0;
}

int seqlist_fetch(seqlist_t *mylist, const void *key, cmp_t cmp, void *data)
{
	int f;

	f = __find(mylist, key, cmp);
	if (-1 == f)
		return -1;
	// 删除下标为f元素之前备份数据
	memcpy(data, (char *)mylist->arr + f * mylist->size, mylist->size);

	memmove((char *)mylist->arr + f * mylist->size, \
			(char *)mylist->arr + (f + 1) * mylist->size, \
			(mylist->nmemb - (f + 1)) * mylist->size);
	// 多出来元素 最后一个位置
	memset((char *)mylist->arr + (mylist->nmemb - 1) * mylist->size, 0, mylist->size);
	mylist->nmemb--;

	return 0;
}

void *seqlist_search(const seqlist_t *mylist, const void *key, cmp_t cmp)
{
	int f;

	f = __find(mylist, key, cmp);
	if (-1 == f)
		return NULL;
	return (char *)mylist->arr + f * mylist->size;
}

static void __swap(void *data1, void *data2, int size)
{
	void *t = malloc(size);
	if (NULL == t)
		return ;
	memcpy(t, data1, size);
	memcpy(data1, data2, size);
	memcpy(data2, t, size);
}

void seqlist_bubble_sort(const seqlist_t *mylist, cmp_t cmp)
{
	int i, j;
	char *p;
	
	for (i = 0; i < mylist->nmemb - 1; i++) {
		for (j = 0; j < mylist->nmemb - i - 1; j++) {
			p = (char *)mylist->arr + j * mylist->size;
			if (cmp(p, p + mylist->size) > 0) {
				__swap(p, p + mylist->size, mylist->size);		
			}
		}
	}
}

void seqlist_reverse(const seqlist_t *mylist)
{
	int i, j;

	for (i = 0, j = mylist->nmemb - 1; i < j; i++, j--) {
		__swap((char *)mylist->arr + i * mylist->size, (char *)mylist->arr + j * mylist->size, mylist->size);
	}
}



